package cn.dansj.common.utils.http;

import cn.dansj.common.utils.transfer.Verification;

import java.net.*;
import java.util.Enumeration;
import java.util.regex.Pattern;

public abstract class HostUtils {
    public static String getHostName() {
        try {
            InetAddress ip = InetAddress.getLocalHost();
            return ip.getHostName();
        } catch (UnknownHostException e) {
            return "";
        }
    }

    // 判断是否为局域网地址（支持 IPv4 和 IPv6）
    public static boolean isPrivateIpAddress(String ip) {
        return isPrivateIpv4(ip) || isPrivateIpv6(ip);
    }

    // 判断是否为 IPv4 局域网地址
    public static boolean isPrivateIpv4(String ip) {
        // IPv4 正则表达式
        if (!isValidIpv4(ip)) return false;

        // 检查是否在私有地址范围内
        String[] parts = ip.split("\\.");
        int first = Integer.parseInt(parts[0]);
        int second = Integer.parseInt(parts[1]);

        return first == 10 || (first == 172 && (second >= 16 && second <= 31)) || (first == 192 && second == 168) || (ip.equals("127.0.0.1") || ip.equals("0.0.0.0")); // 10.0.0.0/8
    }

    public static String getHost() {
        return getHost(true);
    }

    public static String getHost(boolean privateIp) {
        try {
            Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
            while (networkInterfaces.hasMoreElements()) {
                NetworkInterface network = networkInterfaces.nextElement();
                boolean vmnet = network.getDisplayName().toLowerCase().contains("vmnet");
                boolean docker = network.getDisplayName().toLowerCase().contains("docker");
                if (vmnet || docker) {
                    continue;
                }

                boolean networkUp = network.isUp();
                boolean networkLoopback = network.isLoopback();
                boolean networkPTP = network.isPointToPoint();
                boolean virtual = network.isVirtual();
                Enumeration<InetAddress> addresses = network.getInetAddresses();
                while (addresses.hasMoreElements()) {
                    InetAddress addr = addresses.nextElement();
                    boolean addrLoopBack = addr.isLoopbackAddress();
                    boolean linkLocalAddress = addr.isLinkLocalAddress();
                    boolean siteLocalAddress = addr.isSiteLocalAddress();

                    if (!addrLoopBack && !linkLocalAddress && !virtual && siteLocalAddress == privateIp && !networkLoopback
                            && networkUp && !networkPTP && addr instanceof Inet4Address && addr.isReachable(1000)) {
                        return addr.getHostAddress();
                    }
                }
            }
        } catch (Exception ignore) {
        }

        try {
            InetAddress ip = InetAddress.getLocalHost();
            return ip.getHostAddress();
        } catch (UnknownHostException e) {
            return "127.0.0.1";
        }
    }

    public static String getIpPort(int port) {
        return getIpPort(null, port);
    }

    public static String getIpPort(String ip, int port) {
        return String.format("%s:%s", Verification.checkNotNull(ip) ? ip : getHost(), port);
    }

    // IPv4 正则表达式
    private static final Pattern IPV4_PATTERN = Pattern.compile(
            "^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"
    );

    // IPv6 正则表达式
    private static final Pattern IPV6_PATTERN = Pattern.compile(
            "^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$|" + // 标准 IPv6
                    "^::([0-9a-fA-F]{1,4}:){0,6}[0-9a-fA-F]{1,4}$|" + // 前导双冒号
                    "^[0-9a-fA-F]{1,4}::([0-9a-fA-F]{1,4}:){0,5}[0-9a-fA-F]{1,4}$|" + // 中间双冒号
                    "^([0-9a-fA-F]{1,4}:){1}(:[0-9a-fA-F]{1,4}){1,6}$|" + // 后置双冒号
                    "^([0-9a-fA-F]{1,4}:){2}(:[0-9a-fA-F]{1,4}){1,5}$|" + // 双冒号分隔
                    "^([0-9a-fA-F]{1,4}:){3}(:[0-9a-fA-F]{1,4}){1,4}$|" +
                    "^([0-9a-fA-F]{1,4}:){4}(:[0-9a-fA-F]{1,4}){1,3}$|" +
                    "^([0-9a-fA-F]{1,4}:){5}(:[0-9a-fA-F]{1,4}){1,2}$|" +
                    "^([0-9a-fA-F]{1,4}:){6}(:[0-9a-fA-F]{1,4})$"
    );

    /**
     * 判断 IP 地址是 IPv4 还是 IPv6
     *
     * @param ipAddress IP 地址字符串
     * @return "v4"、"v6" 或 "v0"
     */
    public static String checkIpAddress(String ipAddress) {
        if (isValidIpv4(ipAddress)) {
            return "v4";
        } else if (isValidIpv6(ipAddress)) {
            return "v6";
        } else {
            return "v0";
        }
    }

    public static boolean isValidIpv4(String ipAddress) {
        return IPV4_PATTERN.matcher(ipAddress).matches();
    }

    // 验证是否为合法 IPv6 地址
    private static boolean isValidIpv6(String ip) {
        return IPV6_PATTERN.matcher(ip).matches();
    }

    /**
     * 压缩显示 IPv6 地址
     *
     * @param ipv6 输入的 IPv6 地址（如 "0:0:0:0:0:0:0:1"）
     * @return 压缩后的 IPv6 地址（如 "::1"）
     */
    public static String compressIpv6(String ipv6) {
        // 将地址按冒号分割为 8 个块
        String[] blocks = ipv6.split(":");

        // 1. 去除每个块的前导零
        for (int i = 0; i < blocks.length; i++) {
            blocks[i] = removeLeadingZeros(blocks[i]);
        }

        // 2. 找到最长的连续零块
        int maxZeroStart = -1;
        int maxZeroLength = 0;
        for (int i = 0; i < blocks.length; i++) {
            if (blocks[i].equals("0")) {
                int j = i;
                while (j < blocks.length && blocks[j].equals("0")) {
                    j++;
                }
                int length = j - i;
                if (length > maxZeroLength && length > 1) {
                    maxZeroStart = i;
                    maxZeroLength = length;
                }
            }
        }

        // 3. 压缩最长的连续零块为双冒号 "::"
        if (maxZeroStart != -1) {
            String[] compressedBlocks = new String[blocks.length - maxZeroLength + 1];
            System.arraycopy(blocks, 0, compressedBlocks, 0, maxZeroStart);
            compressedBlocks[maxZeroStart] = "";
            System.arraycopy(blocks, maxZeroStart + maxZeroLength, compressedBlocks, maxZeroStart + 1, blocks.length - maxZeroStart - maxZeroLength);
            blocks = compressedBlocks;
        }

        // 4. 将块拼接为最终的 IPv6 地址
        StringBuilder result = new StringBuilder();
        for (int i = 0; i < blocks.length; i++) {
            if (blocks[i].isEmpty()) {
                if (i == 0 || i == blocks.length - 1) {
                    result.append(":");
                }
                result.append(":");
            } else {
                result.append(blocks[i]);
                if (i != blocks.length - 1) {
                    result.append(":");
                }
            }
        }

        return result.toString();
    }

    /**
     * 去除字符串中的前导零
     *
     * @param block 输入的块（如 "0001"）
     * @return 去除前导零后的块（如 "1"）
     */
    private static String removeLeadingZeros(String block) {
        if (block.length() == 1) {
            return block; // 只有一个字符，直接返回
        }
        int i = 0;
        while (i < block.length() && block.charAt(i) == '0') {
            i++;
        }
        return i == block.length() ? "0" : block.substring(i);
    }

    // 判断是否为 IPv6 局域网地址
    public static boolean isPrivateIpv6(String ip) {
        String compressedIp = compressIpv6(ip);
        // IPv6 正则表达式
        if (!isValidIpv6(compressedIp)) {
            return false;
        }

        // 检查是否在私有地址范围内
        return compressedIp.startsWith("fc") || compressedIp.startsWith("fd") || compressedIp.equals("::1"); // fc00::/7
    }
}
